/*
 * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef OHOS_CODEC_DATA
#define OHOS_CODEC_DATA

#include "ohos_video_common.h"

#include <multimedia/player_framework/native_avcodec_base.h>

namespace ohos {

AvBufferInfo::AvBufferInfo(int32_t indx, OH_AVBuffer *buff) {
	index_ = indx;
	buff_ = buff;
}

AvBufferInfo::~AvBufferInfo() {
}

int32_t AvBufferInfo::Index() const {
	return index_;
}

uint8_t *AvBufferInfo::AvBufferAddr() {
	AVCODEC_CHECK(buff_ == nullptr, "avbuffer is not initted!", nullptr);
	return OH_AVBuffer_GetAddr(buff_);
}

int32_t AvBufferInfo::Attr(OH_AVCodecBufferAttr *attr) {
	AVCODEC_CHECK(attr == nullptr, "Attr is NULL", -1);
	AVCODEC_CHECK(buff_ == nullptr, "avbuffer is not initted!", -1);
	memcpy(&attr_, attr, sizeof(OH_AVCodecBufferAttr));

	return OH_AVBuffer_SetBufferAttr(buff_, attr);
}

const OH_AVCodecBufferAttr *AvBufferInfo::Attr() {
	if (OH_AVBuffer_GetBufferAttr(buff_, (OH_AVCodecBufferAttr *)&attr_) != AV_ERR_OK) {
		return nullptr;
	}

	return &attr_;
}

int32_t AvBufferInfo::AvBufferSize() {
	AVCODEC_CHECK(buff_ == nullptr, "avbuffer is not initted!", -1);
	return OH_AVBuffer_GetCapacity(buff_);
}

uint32_t AvBufferInfo::Flag() {
	return attr_.flags;
}

int64_t AvBufferInfo::Pts() {
	return attr_.pts;
}

void convert_nv21_to_yuv420p(MSPicture *dest, uint8_t *buff) {
	int w = dest->w;
	int h = dest->h;
	int y_size = w * h;

	uint8_t *src_y = buff;
	uint8_t *src_vu = buff + y_size;

	// 复制 Y 平面
	memcpy(dest->planes[0], src_y, y_size);

	uint8_t *dst_u = dest->planes[1];
	uint8_t *dst_v = dest->planes[2];

	for (int j = 0; j < h / 2; j++) {
		for (int i = 0; i < w / 2; i++) {
			int vu_index = j * w + i * 2;
			int uv_index = j * (w / 2) + i;

			dst_v[uv_index] = src_vu[vu_index];     // V 分量
			dst_u[uv_index] = src_vu[vu_index + 1]; // U 分量
		}
	}
}

void write_nv21_to_mspicture(MSPicture *pic, uint8_t *addr, int width, int height, int stride) {
	pic->w = width;
	pic->h = height;
	pic->strides[0] = stride;
	pic->strides[1] = stride;

	uint8_t *ySrc = addr;
	uint8_t *uvSrc = addr + width * height;
	uint8_t *yDst = pic->planes[0];
	uint8_t *uvDst = pic->planes[1];

	// 拷贝 Y 平面逐行
	for (int row = 0; row < height; ++row) {
		memcpy(yDst + row * stride, ySrc + row * width, width);
	}

	// 拷贝 UV 平面逐行 (每行为 width bytes，height/2 行)
	int halfH = height / 2;
	for (int row = 0; row < halfH; ++row) {
		memcpy(uvDst + row * stride, uvSrc + row * width, width);
	}

	// 未使用 planes[2] 和 planes[3]
	pic->planes[2] = pic->planes[3] = NULL;
	pic->strides[2] = pic->strides[3] = 0;
}
} // namespace ohos

#endif // OHOS_CODC_DATA
